# -*- coding: utf-8 -*-
# 各种格式校验

import re

try:
    from typing.re import Pattern
except Exception:
    Pattern = re.compile(r"")


class RegType:
    ALL = r'.*'

    USERNAME = r'[a-zA-Z0-9_\-]{1,}'
    # 密码长度不少于8位，且密码中至少包含数字、大小字母和特殊符号的正则表达式（四种里至少三种，且至少8位）
    PASSWORD = r'^(?:(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[~!@#$%^&*()_+`\-={}:";\'<>?,.\/\.]).{8,}|(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,}|(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*()_+`\-={}:";\'<>?,.\/\.]).{8,}|(?=.*[a-z])(?=.*[0-9])(?=.*[~!@#$%^&*()_+`\-={}:";\'<>?,.\/\.]).{8,}|(?=.*[A-Z])(?=.*[0-9])(?=.*[~!@#$%^&*()_+`\-={}:";\'<>?,.\/\.]).{8,})$'
    CHANGED_PASSWORD = r'[0-9a-f]{32}'
    EMAIL = r'([a-zA-Z0-9_\.\-])+\@([a-zA-Z0-9\-])+(\.([a-zA-Z0-9]{2,6}))+'
    MOBILE = r'(1[3-9][0-9])[0-9]{8}'
    PHONE = r'(\(((010)|(021)|(0\d{3,4}))\)( ?)([0-9]{7,8}))|((010|021|0\d{3,4}))([- ]?)([0-9]{7,8})|([0-9]{7,8})'
    PHONE_COMMON = r'([0-9]{3}[_ -][0-9]{8}|[0-9]{4}-[0-9]{7}|[0-9]{8}|1[0-9]{10})'
    IDENTITIY_CARD = r'([1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[Xx\d])'
    # 正数，最多两位小数
    DECIMAL = r'^(?=.{1,10}$)[0-9]+(\.[0-9]{1,2})?$'

    COLUMN_ID = r'[a-fA-F0-9]{24}'

    INVALID_TITLE = r';|:|\?|\'|"|\\|\/|@|&|=|\+|\^|\$|\{|\}|\||\[|\]|`|<|>|#|%'

    FORM_GET = r'application/x-www-form-urlencoded'
    FORM_FILE = r'multipart/form-data'
    HTML_TAG = r'</?(span|tr|hr|br|p|script)/?>'
    ALL_HTML_ATG = r'</?((.|\s)*?)/?>'
    ALL_HTML_SPACE = r'&nbsp;'
    REQUEST_HEADER = r'httputil'

    CH = r'[^\u0000-\u00FF]*'
    NUMBER = r'[-]?[0-9]+(\.[0-9]+){0,1}'
    MONTH = r'0?[1-9]|1[0-2]'
    DAY = r'(0?[1-9])|((1|2)[0-9])|(3[01])'
    TIME = r'(0?[1-9]|1[0-9]|2[0-4])((:|-|\/|\\)(0?[0-9]|[1-5][0-9])){2}'
    DATE = r'[1-9][0-9]{0,3}(?:年|\||\\|\/|\s|,|、|-)(0?[1-9]|1[0-2])(?:月|\||\\|\/|\s|,|、|-)((0?[1-9])|((1|2)[0-9])|(3[01]))日?'
    BIRTHDAY = r'(19|20)[0-9]{2}(:|-|\/|\\)(((0?[1-9]|1[0-2])(:|-|\/|\\)(0?[1-9]|1[0-9]|2[0-9]))|((0?[13-9]|1[0-2])(:|-|\/|\\)(30))|((0?[13578]|1[02])(:|-|\/|\\)(31)))'
    CREDIT = '[1-9][0-9]{5}[1-9][0-9]{3}((0[0-9])|(1[0-2]))(([0|1|2][0-9])|3[0-1])[0-9]{3}([0-9]|x|X)'
    URL = r'((http|ftp|https)://)?(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}(\.[0-9]{1,3}){3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\&%_\./-~-]*)?'
    IPV4AGENT = r'192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2[0-9]|3[01])'
    IPV4 = r'[0-9]{1,3}(\.[0-9]{1,3}){3}'
    IPV6 = r'[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})'

    AGGFUNC_COUNT = r'count'
    AGGFUNC_NUNIQ = r'nuniq'
    AGGFUNC_SUM = r'sum'
    AGGFUNC_MEAN = r'mean'
    AGGFUN_MEDIAN = r'median'
    AGGFUNC_MAX = r'max'
    AGGFUNC_MIN = r'min'
    AGGFUNC_ABS = r'abs'
    AGGFUNC_PROD = r'prod'
    AGGFUNC_STD = r'std'
    AGGFUNC_VAR = r'var'
    AGGFUNC_SEM = r'sem'
    AGGFUNC_SKEW = r'skew'
    AGGFUNC_KURT = r'kurt'
    AGGFUNC_QUANTILE = r'quantile'
    AGGFUNC_CUMSUM = r'cumsum'
    AGGFUNC_CUMPROD = r'cumprod'
    AGGFUNC_LEN = r'len'
    AGGFUNC_FAV_RATE = r'fav_rate'


class Validate:
    @classmethod
    def _find_reg(self, reg_type):
        if reg_type in RegType.__dict__:
            return reg_type
        if isinstance(reg_type, Pattern):
            return reg_type.pattern
        else:
            return reg_type

    @classmethod
    def has(cls, value, reg_type=RegType.ALL):
        try:
            return re.search(r'{0}'.format(cls._find_reg(reg_type)), value, flags=re.M) is not None
        except TypeError:
            return False

    @classmethod
    def any(cls, value, reg_type_list=None):
        try:
            return any(Validate.has(value, reg_type=reg_type) for reg_type in reg_type_list)
        except TypeError:
            return False

    @classmethod
    def start_with(cls, value, reg_type=RegType.ALL):
        try:
            return re.match(r'^({0})'.format(cls._find_reg(reg_type)), value, flags=re.M) is not None
        except TypeError:
            return False

    @classmethod
    def end_with(cls, value, reg_type=RegType.ALL):
        try:
            return re.match(r'.*?({0})$'.format(cls._find_reg(reg_type)), value, flags=re.M) is not None
        except TypeError:
            return False

    @classmethod
    def check(cls, value, reg_type=RegType.ALL):
        try:
            return re.match(r'^{0}$'.format(cls._find_reg(reg_type)), value, flags=re.M) is not None
        except TypeError:
            return False

    @classmethod
    def clear(cls, value, reg_type=RegType.ALL):
        try:
            return re.sub(r'{0}'.format(cls._find_reg(reg_type)), "", value, flags=re.M)
        except TypeError:
            return value

    @classmethod
    def getall(cls, value, reg_type=RegType.ALL):
        try:
            result = re.findall(r'({0})+'.format(cls._find_reg(reg_type)), value, flags=re.M)
            if len(result) > 0 and isinstance(result[0], tuple):
                return [value[0] for value in result]
            return result
        except TypeError:
            return []


"""
示例如下：
"""
if __name__ == '__main__':
    print(Validate.check(None, RegType.DECIMAL))
# if not Validate.check(str(mobile).strip(), RegType.MOBILE):
#     raise ValidationError(code=ValidationError.PhoneError, msg='手机号有误,请重新输入')
